<template>
	<div ref="editorContainer" class="json-editor"></div>
</template>

<script setup>
	import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
	import * as monaco from 'monaco-editor'

	const props = defineProps({
		modelValue: {
			type: [Object, String],
			default: () => ({})
		},
		theme: {
			type: String,
			default: 'vs-dark'
		},
		readOnly: {
			type: Boolean,
			default: false
		}
	})

	const emit = defineEmits(['update:modelValue'])

	const editorContainer = ref(null)
	let editor = null

	// 初始化 Monaco 环境
	const initMonacoEnvironment = () => {
		window.MonacoEnvironment = {
			getWorker: function (_, label) {
				const workerNameMap = {
					json: 'json.worker.js',
					editor: 'editor.worker.js'
				}
				const workerName = workerNameMap[label] || 'editor.worker.js'
				const workerPath = `/node_modules/monaco-editor/esm/vs/language/json/${workerName}`
				return new Worker(workerPath, { type: 'module' })
			}
		}
	}

	// 创建编辑器实例
	const createEditor = () => {
		if (!editorContainer.value) return
		editor = monaco.editor.create(editorContainer.value, {
			value: typeof props.modelValue === 'string' ? props.modelValue : JSON.stringify(props.modelValue, null, 2),
			language: 'json',
			theme: props.theme,
			automaticLayout: true,
			minimap: { enabled: false },
			scrollBeyondLastLine: false,
			lineNumbers: 'on',
			roundedSelection: false,
			contextmenu: false,
			formatOnPaste: true,
			formatOnType: true,
			folding: {
				enabled: true
			}
		})

		// 配置 JSON 校验
		monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
			validate: true,
			schemaValidation: 'error',
			trailingCommas: 'error'
		})

		// 监听内容变化
		editor.onDidChangeModelContent(() => {
			const value = editor.getValue()
			try {
				const json = JSON.parse(value)
				emit('update:modelValue', json)
			} catch (e) {
				console.error('JSON 格式错误:', e)
			}
		})
	}

	// 响应式更新
	watch(
		() => props.modelValue,
		(newVal) => {
			console.log(newVal)
			const currentValue = editor?.getValue()
			const newValue = typeof newVal === 'string' ? newVal : JSON.stringify(newVal, null, 2)

			if (currentValue !== newValue) {
				editor?.setValue(newValue)
			}
		},
		{
			deep: true,
			immediate: true
		}
	)

	onMounted(() => {
		initMonacoEnvironment()
		createEditor()
	})

	onBeforeUnmount(() => {
		editor?.dispose()
	})

	// 暴露公共方法
	defineExpose({
		format: () => {
			editor?.getAction('editor.action.formatDocument').run()
		},
		toggleFold: (position) => {
			editor?.toggleFold(position)
		}
	})
</script>

<style scoped>
	.json-editor {
		height: 400px;
		border: 1px solid #ddd;
		border-radius: 2px;
		overflow: hidden;
	}
</style>
